#loading packages
library(lubridate)
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.3.2 ✓ purrr 0.3.4
## ✓ tibble 3.0.5 ✓ stringr 1.4.0
## ✓ tidyr 1.1.2 ✓ forcats 0.5.0
## ✓ readr 1.4.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x lubridate::as.difftime() masks base::as.difftime()
## x lubridate::date() masks base::date()
## x dplyr::filter() masks stats::filter()
## x lubridate::intersect() masks base::intersect()
## x dplyr::lag() masks stats::lag()
## x lubridate::setdiff() masks base::setdiff()
## x lubridate::union() masks base::union()
library(ggridges) # for joy plots
library(plotly)
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
library(gganimate) # for adding animation layers to ggplots
library(gifski) # for creating the gif (don't need to load this library every time,but need it installed)
#loading data
spotify <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-01-21/spotify_songs.csv')
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## .default = col_double(),
## track_id = col_character(),
## track_name = col_character(),
## track_artist = col_character(),
## track_album_id = col_character(),
## track_album_name = col_character(),
## track_album_release_date = col_character(),
## playlist_name = col_character(),
## playlist_id = col_character(),
## playlist_genre = col_character(),
## playlist_subgenre = col_character()
## )
## ℹ Use `spec()` for the full column specifications.
spotify_rap <- spotify %>%
filter(playlist_genre == "rap")
randb <- spotify %>%
filter(playlist_genre == "r&b") %>%
select(-track_id, - track_album_id, -playlist_id, -playlist_name) %>%
filter(track_popularity >= 75)
Introduction & Background
A noticeable trend in the entertainment industry has been the transformation from physical to digitalized content. Newspapers are replaced with online articles, Netflix replaced Blockbuster, and online music streaming sites like Spotify have taken over traditonal music media as the primary source of music for millions. In addition to expanding the reach of music to new people, the transition to using Spotify has come with new ways to analyze music tastes, both individually and as a population. Spotify users have access to new daily playlists tailored to their individual preferences, in addition to having suggested music based of the data provided to Spotify of listening habits. In our analysis of the characteristics of songs, we hope to make obserations to help pinpoint what exactly makes a song popular.
Data Collection
Retrieved from a past Tidy Tuesday dataset, we will be using data from Spotify for our analysis. The link to the repository can be can be accessed here
Using data provided by Spotify, we will investigate how certain aspects of a song, such as genre, subgenre, release date, and other more complex measurements correlate to how popular a song is according to Spotify. Popularity is rated on a scale to 100 with the most popular songs on Spotify as of February 2020 will have a score near 100. We identified popularity scores greater than 75 to be a convenient threshold to deem a song “popular”.
implications of using the data, any biases in the data?
A General Analysis
How has the popularity of genres changed over time?
genre_pop <- spotify %>%
filter(track_popularity >= 75) %>%
mutate(ymd_release = ymd(track_album_release_date),
year = year(ymd_release)) %>%
group_by(year, playlist_genre) %>%
summarize(avg_popularity = mean(track_popularity)) %>%
ggplot(aes(x = year, y = avg_popularity, color = playlist_genre)) +
geom_point() +
labs(title="Average song popularity by genre per year",
subtitle = "Overall, as music becomes more accessible, average peopulatity across all genres is on the rise.",
x = "",
y = "",
color = "Genre") +
theme_classic()
## Warning: Problem with `mutate()` input `ymd_release`.
## ℹ 68 failed to parse.
## ℹ Input `ymd_release` is `ymd(track_album_release_date)`.
## Warning: 68 failed to parse.
## `summarise()` regrouping output by 'year' (override with `.groups` argument)
ggplotly(genre_pop)
The graph above shows how track popularity has trended by genre since. Though Spotify has a wide variety of songs, based on the plot rock is the only genre that has any significant foundations of popular songs from before the 1980s and 90s. Since then however, song popularity across every genre has experienced exponential growth in popularity, most notably with the introduction of pop and edm. As music becomes easier to produce and release from informal settings, today, a studio and expensive equipment are not necessary to make good music. This is also show in the visualization above with the quantity of cases dramtically increasing with teh advent of teh 21st century.
How does does song popularity vary based on genre?
prelim_graph <- spotify %>%
ggplot(aes(y = playlist_genre, x = track_popularity)) +
labs(title = "Song Popularity by Genre",
x = "", y = "",
subtitle = "Song popularity is measured from 0-100, with higher numbers being indiciative of more popularity.\nHighest median popularities belong to pop and latin with an overall median popularity of 40",
caption = "Alex Ismail, Malek Kaloti, Brian Lee") +
theme_classic() +
theme(plot.title.position = "plot",
plot.title = element_text(size = 20, face = "bold"),
plot.subtitle = element_text(size = 10, face = "italic")) +
geom_boxplot() +
geom_vline(aes(xintercept = median(track_popularity, na.rm = TRUE)), color = "blue")
prelim_graph

The box plot above compares distribution of song popularity by genre again, however this time including the songs not deemed popular. EDM music is noticeably behind in median popularity compared to the universal median of ~40, while pop, latin, and to lesser degree rap show a slight advantage over the other genres in median.
Analysis: Diving deeper into our favorite genres
Rap
Rap is a particularly fascinating genre to investigate using the Spotify data to look at what traits of music have correlated with popularity as the genre has undergone several changes in audience and style. Though a relatively new genre arriving on the greater music scene in the 80s, rap has undergone a myriad of trends and style variations. Fans of old school rap from the 80s and 90s may have distaste for today’s artists like Drake and Eminem for having modernized the genre too much. Fans of modern rap may get bored of the authentic sound of artists like Run-DMC or Tupac. Are there trends that tie all of rap together as to what makes a song popular?
Song Quality
The first and most natural observations to make are on overarching metrics that Spotify provides. Using the descriptions provided, I was most interested on the following values in correlation to track popularity: Danceability due to rap’s heavy emphasis on rhythm and beats, Energy due to some artists’ signature style of shouting to “hype” up a crowd (ie. Lil Jon, DMX), the inverse variables of Speechiness/Instrumentalness due to other artist’s signature of rapping as fast as possible (ie. Eminem, Busta Rhymes), and Valence for the perceived association between rap and violence, drugs, and focus on other less-than-righteous topics.
## `summarise()` regrouping output by 'Stat1' (override with `.groups` argument)
## Warning: Problem with `mutate()` input `Stat`.
## ℹ Unknown levels in `f`: Rounded_Energy, Rounded_Speechiness, Rounded_Instrumental, Rounded_Valence
## ℹ Input `Stat` is `fct_recode(...)`.
## ℹ The error occurred in group 1: Stat1 = "Rounded_Danceability".
## Warning: Unknown levels in `f`: Rounded_Energy, Rounded_Speechiness,
## Rounded_Instrumental, Rounded_Valence
## Warning: Problem with `mutate()` input `Stat`.
## ℹ Unknown levels in `f`: Rounded_Danceability, Rounded_Speechiness, Rounded_Instrumental, Rounded_Valence
## ℹ Input `Stat` is `fct_recode(...)`.
## ℹ The error occurred in group 2: Stat1 = "Rounded_Energy".
## Warning: Unknown levels in `f`: Rounded_Danceability, Rounded_Speechiness,
## Rounded_Instrumental, Rounded_Valence
## Warning: Problem with `mutate()` input `Stat`.
## ℹ Unknown levels in `f`: Rounded_Danceability, Rounded_Energy, Rounded_Speechiness, Rounded_Valence
## ℹ Input `Stat` is `fct_recode(...)`.
## ℹ The error occurred in group 3: Stat1 = "Rounded_Instrumental".
## Warning: Unknown levels in `f`: Rounded_Danceability, Rounded_Energy,
## Rounded_Speechiness, Rounded_Valence
## Warning: Problem with `mutate()` input `Stat`.
## ℹ Unknown levels in `f`: Rounded_Danceability, Rounded_Energy, Rounded_Instrumental, Rounded_Valence
## ℹ Input `Stat` is `fct_recode(...)`.
## ℹ The error occurred in group 4: Stat1 = "Rounded_Speechiness".
## Warning: Unknown levels in `f`: Rounded_Danceability, Rounded_Energy,
## Rounded_Instrumental, Rounded_Valence
## Warning: Problem with `mutate()` input `Stat`.
## ℹ Unknown levels in `f`: Rounded_Danceability, Rounded_Energy, Rounded_Speechiness, Rounded_Instrumental
## ℹ Input `Stat` is `fct_recode(...)`.
## ℹ The error occurred in group 5: Stat1 = "Rounded_Valence".
## Warning: Unknown levels in `f`: Rounded_Danceability, Rounded_Energy,
## Rounded_Speechiness, Rounded_Instrumental

Oddly, the biggest conclusion I drew from this graph was not any positive or negative correlation, but a lack of connection between valence and popularity. For a genre that has a reputation for being connected with gangs, guns, drugs, etc., there is a complete lack of correlation between valence and popularity. Beyond that, there is a moderately strong correlation between popularity and danceability, as I had expected based on the prevalence of beats and rhythms in rap. The energy line shows that the highest percentage of songs to become popular are ~.5 energy, which likely suggests too much energy can take away from the popularity of a song. Finally, the speechiness/instrumentalness variable shows that songs on the extreme end of speechiness (.8+) are most likely to be popular.
Do songs with multiple artists become popular at a higher rate?
Beyond the stats, there was one more observation I wanted to make on rap music. Based on my experience listening to rap, some of my favorite songs are remixes, features, or any other way multiple artists can put verses on the same song. Songs like “Life is Good” by Drake and Future, or remixes to songs like “HIGHEST IN THE ROOM” which incorporates Lil Baby in a song by Travis Scott add a certain level of freshness and break up three consecutive minutes of one artist rapping into fun back and forths with styles. Below is a graphic comparing the popularity rates of those songs vs solo songs between rap and other genres.
Multiple_Artist_Graph <- spotify %>%
mutate(track_name_lower = str_to_lower(track_name),
remix = str_detect(track_name_lower, "Remix"),
feature = str_detect(track_name_lower, "feat"),
ma_prep = remix|feature,
ma_prep2 = replace_na(ma_prep, FALSE),
multiple_artists = if_else(ma_prep2, true = "Multiple Artists", false = "One Artist"),
popular = track_popularity > 75) %>%
group_by(multiple_artists, playlist_genre) %>%
summarize(prop_pop = mean(popular)*100) %>%
mutate(genre = fct_relevel(playlist_genre, "rap")) %>%
ggplot() +
geom_col(aes(x = multiple_artists, y = prop_pop), fill = "black") +
facet_wrap(~genre) +
labs(title = "Popularity of Songs Containing Mulitple Artists Across Genre",
x = "", y = "Percent of Songs Popular") +
theme_classic() +
theme(plot.title.position = "plot",
plot.title = element_text(size = 20, face = "bold"),
plot.subtitle = element_text(size = 10, face = "italic"))
## `summarise()` regrouping output by 'multiple_artists' (override with `.groups` argument)
ggplotly(Multiple_Artist_Graph)
## Warning: `group_by_()` is deprecated as of dplyr 0.7.0.
## Please use `group_by()` instead.
## See vignette('programming') for more help
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_warnings()` to see where this warning was generated.
Rap had the largest change between songs with multiple artists and song with only one, with a gap of 10%. Based on other genres’ disparity like R&B and pop, I hypothesize that these trends are connected with the modern day music scene. Collaboration between artists at the top of their field has become more commonplace, even with some mega-tracks like “Forever” with verses from Eminem, Kanye West, Drake, and Lil Wayne all in the same song. These collaborations can create songs with blended styles, which even furthers the development of rap as a unique genre.
R&B
Why R&B?
In this section, I want to take a closer look at one of my favorite genres of music, R&B. I think I love it so much because it’s often good music to unwind to – it’s smooth, slow, and relaxing. I also love its versatility! R&B can fit the mood of anything from a gloomy, rainy day to a bright, sunny day. But why? What characteristics make R&B such a great genre to listen to? Using the Spotify dataset and some visualizations which look at the specific characteristics of the most popular R&B songs (songs with a popularity rating of above 75), I hope to come closer to answering these questions.
randb %>%
select(track_name, track_artist, playlist_genre, playlist_subgenre, track_popularity, danceability, energy, loudness, mode, speechiness, acousticness, instrumentalness, liveness, valence, duration_ms) %>%
arrange(desc(track_popularity)) %>%
head(12) %>%
knitr::kable()
| ROXANNE |
Arizona Zervas |
r&b |
urban contemporary |
99 |
0.621 |
0.601 |
-5.616 |
0 |
0.1480 |
0.05220 |
0.000000 |
0.4600 |
0.457 |
163636 |
| ROXANNE |
Arizona Zervas |
r&b |
hip pop |
99 |
0.621 |
0.601 |
-5.616 |
0 |
0.1480 |
0.05220 |
0.000000 |
0.4600 |
0.457 |
163636 |
| The Box |
Roddy Ricch |
r&b |
urban contemporary |
98 |
0.896 |
0.586 |
-6.687 |
0 |
0.0559 |
0.10400 |
0.000000 |
0.7900 |
0.642 |
196653 |
| Memories |
Maroon 5 |
r&b |
urban contemporary |
98 |
0.764 |
0.320 |
-7.209 |
1 |
0.0546 |
0.83700 |
0.000000 |
0.0822 |
0.575 |
189486 |
| Blinding Lights |
The Weeknd |
r&b |
urban contemporary |
98 |
0.513 |
0.796 |
-4.075 |
1 |
0.0629 |
0.00147 |
0.000209 |
0.0938 |
0.345 |
201573 |
| Blinding Lights |
The Weeknd |
r&b |
hip pop |
98 |
0.513 |
0.796 |
-4.075 |
1 |
0.0629 |
0.00147 |
0.000209 |
0.0938 |
0.345 |
201573 |
| The Box |
Roddy Ricch |
r&b |
hip pop |
98 |
0.896 |
0.586 |
-6.687 |
0 |
0.0559 |
0.10400 |
0.000000 |
0.7900 |
0.642 |
196653 |
| Tusa |
KAROL G |
r&b |
hip pop |
98 |
0.803 |
0.715 |
-3.280 |
1 |
0.2980 |
0.29500 |
0.000134 |
0.0574 |
0.574 |
200960 |
| Memories |
Maroon 5 |
r&b |
hip pop |
98 |
0.764 |
0.320 |
-7.209 |
1 |
0.0546 |
0.83700 |
0.000000 |
0.0822 |
0.575 |
189486 |
| Circles |
Post Malone |
r&b |
hip pop |
98 |
0.695 |
0.762 |
-3.497 |
1 |
0.0395 |
0.19200 |
0.002440 |
0.0863 |
0.553 |
215280 |
| Don’t Start Now |
Dua Lipa |
r&b |
urban contemporary |
97 |
0.794 |
0.793 |
-4.521 |
0 |
0.0842 |
0.01250 |
0.000000 |
0.0952 |
0.677 |
183290 |
| everything i wanted |
Billie Eilish |
r&b |
urban contemporary |
97 |
0.704 |
0.225 |
-14.454 |
0 |
0.0994 |
0.90200 |
0.657000 |
0.1060 |
0.243 |
245426 |
Above are the top 10 most popular songs in the R&B genre (12 songs were pulled from the dataset to account for 2 songs that were each in 2 different subgenres – Arizona Zeravas’ Roxanne and The Weeknd’s Blinding Lights. We can see that all of them were released in 2019 and all categorized under my two favorite two subgenres of R&B, Urban Contemporary and Hip Pop. All of them also boast a danceability score of above 0.5, with most of them (with the exception of Maroon 5’s Memories and Billie Eilish’s everything i wanted) having energy scores of above 0.5. We can also see that across the board, all 10 songs have low speechiness and instrumentalness scores (with the exception of Billie Eilish’s everything i wanted. Interestingly, all of the songs fall within a valence of 0.2-0.6. The other characteristics are quite varied. So, for the purposes of my analysis of the R&B genre, I will only focus on the song characteristics that have clear trends across the genre – danceabiility, energy, speechiness, instrumentalness, and valence.
Which subgenres have the most popular songs?
In the exploratory phase of my analysis of the R&B genre, the most obvious characteristic of a song in the R&B genre was a song’s subgenre. Are certain genres more likely to have more popular songs because some have more fans and listeners than others? In the density plot below, we see that this is the case – Neo-Soul and New Jack Swing have the highest quantity of popular songs.
randb %>%
ggplot(aes(x = track_popularity, fill = playlist_subgenre)) +
geom_density(alpha = 0.1) +
theme_classic() +
labs(title = "Do certain subgenres have more popular songs?",
subtitle = "This density plot only includes songs with a popularity of >=75.\nIt seems that Neo-Soul and New Jack Swing have the most popular songs.\n\nR&B Subgenre: {closest_state}",
x = "Track Popularity",
y = "",
fill = "R&B subgenre",
caption = "Visualization created by Brian Lee") +
transition_states(playlist_subgenre, transition_length = 3, state_length = 1)
#get rid of axes, make subtitle descriptive
anim_save("randb_density.gif")
knitr::include_graphics("randb_density.gif")

In the density plot above, Neo-Soul and New Jack Swing both seem to have a lot of popular songs on the lower end of the spectrum (75-85), with Urban Contemporary and Hip Pop following similar trends, but in comparison to the other two genres, their density curves are not as large, signaling that the former two genres have more songs classified as “popular” than teh latter two.
I believe that this trend could be occurring because of the huge increase in the production of hip pop and urban contemporary music. With streaming services such as Spotify making it easier than ever for small creators to attain platforms and with the advancement of technology making it easier to produce and release music from one’s own bedroom, this may be because of the oversaturation of the music industry – there are more songs being released than ever.
randb %>%
group_by(playlist_subgenre) %>%
summarize(num_of_songs = n(), avg_pop = mean(track_popularity)) %>%
knitr::kable()
## `summarise()` ungrouping output (override with `.groups` argument)
| hip pop |
281 |
82.95018 |
| neo soul |
41 |
78.90244 |
| new jack swing |
4 |
77.50000 |
| urban contemporary |
204 |
82.13725 |
Despite the large density curves, on average, hip pop and urban contemporary are slightly more popular than the Neo-Soul and New Jack Swing. Another interesting observation we can make is the sheer lack of popular songs for Neo-Soul and New Jack Swing.
A quick Google search will reveal that both Neo-Soul and New Jack Swing were subgenres of R&B that were popular during the 1980’s/90’s. Their large density curves could be due to this fact. Because the technology for household high quality handheld microphones and producing equipment was not in abundance like it is now, artists had to rely on label companies and managers for the funding to acquire the money for studios and expensive equipment, thus leading to less music being produced. Additionally, because labeling agencies and managerial agencies essentially “invested” in discovered artists whom they knew they would get a high profit margin from, the discovered artists who were given a platform by these agencies were more likely to be successful. With a smaller pool of music and more popular songs making up that small poool of music, large density curves such as the ones we see in the visualization above for Neo-Soul and New Jack Swing are possible, and could serve as an explanation for the difference in the quantity between the four genres.
As I move forward in my analysis to look at the specific characteristics of popular R&B songs, I will restrict myself to the two subgenres with more cases to look at and my person two favorite subgenres – Hip-Pop and Urban Contemporary.
Taking a closer look at the specific characteristics of popular songs in the Hip-Pop and Urban Contemporary Subgenres
randb2 <-randb %>%
group_by(playlist_subgenre) %>%
filter(playlist_subgenre == c("hip pop", "urban contemporary")) %>%
summarise_at(c("track_popularity", "danceability", "energy", "speechiness", "instrumentalness", "valence"), mean, na.rm = TRUE)
## Warning in playlist_subgenre == c("hip pop", "urban contemporary"): longer
## object length is not a multiple of shorter object length
## Warning in playlist_subgenre == c("hip pop", "urban contemporary"): longer
## object length is not a multiple of shorter object length
#knitr::kable()
Looking at the table above, we see that the values for each characteristic are nearly identical, often just 0.01 off from each other. Additionally, with the popularity of the two subgenres being so close to each other, it’s safe to say that high danceability, energy, and valence are traits that are seen in popular songs of both subgenres – Hip Pop and Urban Contemporary. On the contrary, popular songs of both subgenres are speechiness and instrumentalness This does make logical sense, as R&B is often on the slower, smoother side, hence the low speechiness (contrary to rap).
For popular songs of the two subgenres where high danceability, energy, and valence, are prevalent, I believe that this follows general trends across genres, where people want to listen to upbeat, energetic music that they can dance to. Apparently, R&B listeners tend to be in favor of songs that have vocal singing without many lyrics due to the low speechiness value and instrumentalness values – songs with lots of “oohs” and “ahs”, as defined by the codebook on the repository page which says that the closer intrumentalness is to 1.0, the greater likelihood the track contains no vocal content. It also notes that “Ooh” and “aah” sounds are treated as instrumental in this context.
R&B – Analysis Conclusion
All in all, I believe that R&B follows overall trends of popular music across all genres, as seen with the high values for danceability, valence, and energy. The defining difference, and what sets R&B apart from the other genres, is the low values for instrumentalness and speechiness. I also discovered that what I love abour R&B is actuallly what makes it popular! Hopefully, these discoveries and my analysis of genre’s characrteristics will help me and others find more relevant R&B recommendations.
Pop
Who hasn’t been in a “aaah, I know this song” moment but didn’t know where they knew it from? Or even worse, singing the lyrics of a song you hate because you couldn’t help but memorize them since the track was playing everywhere. Chances are, you heard that tune on the car radio when your phone’s battery died or maybe even at the store when you went to buy a charger for your phone. These songs that we often find impossible to get out of our head are in many cases top hit songs; hence the reason they’re everywhere. But what makes these popular songs.
We cannot talk about popular music without crossing pop music. In fact, the terms popular music and pop music are often used interchangeably. This genre has a formula that charges up our adrenaline levels and give us no choice but to dance to the beat, even if it was only a couple of shoulder shrugs. I personally find myself helpless to a good pop beat. Nevertheless, not all pop music give us the same adrenaline rush; popular ones seem to have a twist in the formula.
I am curious whether popular pop tracks have different attributes that make them hit the top chart lists. And so, I want to compare the data for the features of tracks to see if the secret for their success lies in technical features.
feature_names <- names(spotify)[12:23]
spotify %>%
filter(playlist_genre == "pop") %>%
mutate(is_popular = ifelse(track_popularity >= 75, T, F)) %>%
select(c(is_popular, feature_names)) %>%
pivot_longer(cols = feature_names) %>%
ggplot(aes(x = value)) +
geom_density(aes(color = is_popular), alpha = 0.5) +
facet_wrap(~name, ncol = 3, scales = 'free') +
labs(title = "Popular vs. Unpopular Spotify Audio Feature Density",
x = element_blank(),
y = element_blank()) +
theme(axis.text.y = element_blank()) +
scale_color_discrete(name = element_blank(),
labels = c("unpopular", "popular"))
## Note: Using an external vector in selections is ambiguous.
## ℹ Use `all_of(feature_names)` instead of `feature_names` to silence this message.
## ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
## This message is displayed once per session.

Looking at the data from the plot above, it seems that the most distinguishable difference that makes popular pop tracks stand out is their danceability. This can be seen from the peak shifted to the right for danceabilty. One thing that surprised me was to see that popular pop tracks tend to have slightly lower energy and loudness values. It seems that popular pop tracks tend to focus on other aspects to make the song feel more energizable. Nevertheless, it can be said that these technical features aren’t what distinguish the tracks that make it to the top charts.
What now? Why is our analysis important?
As it becomes easier to produce and release music from one’s own bedroom and streaming platforms such as Apple Music and Spotify increasingly making music accessible to everyone, we believe our analysis has important implications which can help listeners find new songs that they like and help platforms build algorithms that give better and more relevant song recommendations to its users.
An Acknowledgement: Correlation does no equal causation.
As we close our analysis of what makes a song popular, it would be remiss if we did not acknowledge that just because we have identified certain characteristics that make a song have a high popularity rating, it does not necessarily mean that if a certain song has all the preferred characteristics that we mentioned in our analyses, it will be popular, as we can never know whether or not something will with 100% certainly. There is also a factor of human behavior that we simply cannot predict using data science. We can try our best to follow trends and to look at graphs, but trying to predict whether or not a song willl be well liked by its audience is something that must be taken with a grain of salt. At its core, the purpose of our analysis was simply to make general observations about trends that caught the eye – not to predict with complete certainty the popularity of a song.
Possibilities for further analysis & A Conclusion
If we had more time, we believe it would be fascinating and useful to build a shiny app where people coul adjust their preferences for features they look for in songs their favorite songs (eg. high danceability, low valence, etc.) so that the app could return recommended songs with similar values. Or, we could have users input their favorite songs to find recommendations based on similar characteristic and song attributes. We could also create playlists, similar to what Spotify does. By determining recommended values for different moods and purposes such as relaxation, meditating, and studying, it would be intersting to see how accurate these playlists are. Again, as we mentioned in the previous section, we cannot predict human judgement, so we do expect some level of human error in determining the “correctness” of the playlists. The possibilities with this dataset are endless!
Thanks to streaming platforms such as Spotify and Apple Music, small creators are also given a platform for creative release. Our analyses of pop, rap, and R&B, can also help small artists grow their own platforms to cater to the interests of specific audiences. In a time such as now when the consumption of art (whether it be in the form of movies, music, or television), is essential to one’s mental wellbeing, our analysis can help boost these efforts. By asking the question, “What makes a song in a given genre popular?” We have taken a close look at the specific characteristics of songs with a popularity rating of 75 or higher.
LS0tCnRpdGxlOiAiV2hhdCBtYWtlcyBhIHNvbmcgcG9wdWxhcj8iCnN1YnRpdGxlOiAiQSBtdXNpY2FsIGFuYWx5c2lzIG9mIHBvcHVsYXIgc29uZ3MgYW5kIHRoZWlyIGNoYXJhY3RlcmlzdGljcyIKYXV0aG9yOiAiQWxleCBJc21haWwsIE1hbGVrIEthbG90aSwgQnJpYW4gTGVlIgpkYXRlOiAiMTMgTWFyY2ggMjAyMSIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAga2VlcF9tZDogVFJVRQogICAgdG9jOiBUUlVFCiAgICB0b2NfZmxvYXQ6IFRSVUUKICAgIGRmX3ByaW50OiBwYWdlZAogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBoaWRlCgogICAgICAKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KI2tuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZXJyb3I9VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSkKYGBgCgpgYGB7cn0KI2xvYWRpbmcgcGFja2FnZXMKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdncmlkZ2VzKSAjIGZvciBqb3kgcGxvdHMKbGlicmFyeShwbG90bHkpIApsaWJyYXJ5KGdnYW5pbWF0ZSkgICAgICMgZm9yIGFkZGluZyBhbmltYXRpb24gbGF5ZXJzIHRvIGdncGxvdHMKbGlicmFyeShnaWZza2kpICAgICAgICAjIGZvciBjcmVhdGluZyB0aGUgZ2lmIChkb24ndCBuZWVkIHRvIGxvYWQgdGhpcyBsaWJyYXJ5IGV2ZXJ5IHRpbWUsYnV0IG5lZWQgaXQgaW5zdGFsbGVkKQpgYGAKCmBgYHtyfQojbG9hZGluZyBkYXRhCnNwb3RpZnkgPC0gcmVhZHI6OnJlYWRfY3N2KCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5L21hc3Rlci9kYXRhLzIwMjAvMjAyMC0wMS0yMS9zcG90aWZ5X3NvbmdzLmNzdicpCgpzcG90aWZ5X3JhcCA8LSBzcG90aWZ5ICU+JSAKICBmaWx0ZXIocGxheWxpc3RfZ2VucmUgPT0gInJhcCIpCgpyYW5kYiA8LSBzcG90aWZ5ICU+JQogIGZpbHRlcihwbGF5bGlzdF9nZW5yZSA9PSAiciZiIikgJT4lCiAgc2VsZWN0KC10cmFja19pZCwgLSB0cmFja19hbGJ1bV9pZCwgLXBsYXlsaXN0X2lkLCAtcGxheWxpc3RfbmFtZSkgJT4lCiAgZmlsdGVyKHRyYWNrX3BvcHVsYXJpdHkgPj0gNzUpCmBgYAoKIyBJbnRyb2R1Y3Rpb24gJiBCYWNrZ3JvdW5kCgpBIG5vdGljZWFibGUgdHJlbmQgaW4gdGhlIGVudGVydGFpbm1lbnQgaW5kdXN0cnkgaGFzIGJlZW4gdGhlIHRyYW5zZm9ybWF0aW9uIGZyb20gcGh5c2ljYWwgdG8gZGlnaXRhbGl6ZWQgY29udGVudC4gTmV3c3BhcGVycyBhcmUgcmVwbGFjZWQgd2l0aCBvbmxpbmUgYXJ0aWNsZXMsIE5ldGZsaXggcmVwbGFjZWQgQmxvY2tidXN0ZXIsIGFuZCBvbmxpbmUgbXVzaWMgc3RyZWFtaW5nIHNpdGVzIGxpa2UgU3BvdGlmeSBoYXZlIHRha2VuIG92ZXIgdHJhZGl0b25hbCBtdXNpYyBtZWRpYSBhcyB0aGUgcHJpbWFyeSBzb3VyY2Ugb2YgbXVzaWMgZm9yIG1pbGxpb25zLiBJbiBhZGRpdGlvbiB0byBleHBhbmRpbmcgdGhlIHJlYWNoIG9mIG11c2ljIHRvIG5ldyBwZW9wbGUsIHRoZSB0cmFuc2l0aW9uIHRvIHVzaW5nIFNwb3RpZnkgaGFzIGNvbWUgd2l0aCBuZXcgd2F5cyB0byBhbmFseXplIG11c2ljIHRhc3RlcywgYm90aCBpbmRpdmlkdWFsbHkgYW5kIGFzIGEgcG9wdWxhdGlvbi4gU3BvdGlmeSB1c2VycyBoYXZlIGFjY2VzcyB0byBuZXcgZGFpbHkgcGxheWxpc3RzIHRhaWxvcmVkIHRvIHRoZWlyIGluZGl2aWR1YWwgcHJlZmVyZW5jZXMsIGluIGFkZGl0aW9uIHRvIGhhdmluZyBzdWdnZXN0ZWQgbXVzaWMgYmFzZWQgb2YgdGhlIGRhdGEgcHJvdmlkZWQgdG8gU3BvdGlmeSBvZiBsaXN0ZW5pbmcgaGFiaXRzLiBJbiBvdXIgYW5hbHlzaXMgb2YgdGhlIGNoYXJhY3RlcmlzdGljcyBvZiBzb25ncywgd2UgaG9wZSB0byBtYWtlIG9ic2VyYXRpb25zIHRvIGhlbHAgcGlucG9pbnQgd2hhdCBleGFjdGx5IG1ha2VzIGEgc29uZyBwb3B1bGFyLgoKIyMgRGF0YSBDb2xsZWN0aW9uCgpSZXRyaWV2ZWQgZnJvbSBhIHBhc3QgVGlkeSBUdWVzZGF5IGRhdGFzZXQsIHdlIHdpbGwgYmUgdXNpbmcgZGF0YSBmcm9tIFNwb3RpZnkgZm9yIG91ciBhbmFseXNpcy4gVGhlIGxpbmsgdG8gdGhlIHJlcG9zaXRvcnkgY2FuIGJlIGNhbiBiZSBhY2Nlc3NlZCBbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9ibG9iL2ZhY2EwYjZiZDI4Mjk5ODY5MzAwN2MzMjllM2Y0YjkxN2E1ZmQ3YTgvZGF0YS8yMDIwLzIwMjAtMDEtMjEvcmVhZG1lLm1kKQoKVXNpbmcgZGF0YSBwcm92aWRlZCBieSBTcG90aWZ5LCB3ZSB3aWxsIGludmVzdGlnYXRlIGhvdyBjZXJ0YWluIGFzcGVjdHMgb2YgYSBzb25nLCBzdWNoIGFzIGdlbnJlLCBzdWJnZW5yZSwgcmVsZWFzZSBkYXRlLCBhbmQgb3RoZXIgbW9yZSBjb21wbGV4IG1lYXN1cmVtZW50cyBjb3JyZWxhdGUgdG8gaG93IHBvcHVsYXIgYSBzb25nIGlzIGFjY29yZGluZyB0byBTcG90aWZ5LiBQb3B1bGFyaXR5IGlzIHJhdGVkIG9uIGEgc2NhbGUgdG8gMTAwIHdpdGggdGhlIG1vc3QgcG9wdWxhciBzb25ncyBvbiBTcG90aWZ5IGFzIG9mIEZlYnJ1YXJ5IDIwMjAgd2lsbCBoYXZlIGEgc2NvcmUgbmVhciAxMDAuIFdlIGlkZW50aWZpZWQgcG9wdWxhcml0eSBzY29yZXMgZ3JlYXRlciB0aGFuIDc1IHRvIGJlIGEgY29udmVuaWVudCB0aHJlc2hvbGQgdG8gZGVlbSBhIHNvbmcgInBvcHVsYXIiLgoKaW1wbGljYXRpb25zIG9mIHVzaW5nIHRoZSBkYXRhLCBhbnkgYmlhc2VzIGluIHRoZSBkYXRhPwoKIyBBIEdlbmVyYWwgQW5hbHlzaXMKCiMjIEhvdyBoYXMgdGhlIHBvcHVsYXJpdHkgb2YgZ2VucmVzIGNoYW5nZWQgb3ZlciB0aW1lPwoKYGBge3J9CmdlbnJlX3BvcCA8LSBzcG90aWZ5ICU+JQogIGZpbHRlcih0cmFja19wb3B1bGFyaXR5ID49IDc1KSAlPiUKICAgIG11dGF0ZSh5bWRfcmVsZWFzZSA9IHltZCh0cmFja19hbGJ1bV9yZWxlYXNlX2RhdGUpLAogICAgICAgICB5ZWFyID0geWVhcih5bWRfcmVsZWFzZSkpICU+JQogIGdyb3VwX2J5KHllYXIsIHBsYXlsaXN0X2dlbnJlKSAlPiUKICBzdW1tYXJpemUoYXZnX3BvcHVsYXJpdHkgPSBtZWFuKHRyYWNrX3BvcHVsYXJpdHkpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gYXZnX3BvcHVsYXJpdHksIGNvbG9yID0gcGxheWxpc3RfZ2VucmUpKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHRpdGxlPSJBdmVyYWdlIHNvbmcgcG9wdWxhcml0eSBieSBnZW5yZSBwZXIgeWVhciIsCiAgICAgICBzdWJ0aXRsZSA9ICJPdmVyYWxsLCBhcyBtdXNpYyBiZWNvbWVzIG1vcmUgYWNjZXNzaWJsZSwgYXZlcmFnZSBwZW9wdWxhdGl0eSBhY3Jvc3MgYWxsIGdlbnJlcyBpcyBvbiB0aGUgcmlzZS4iLAogICAgICAgeCA9ICIiLAogICAgICAgeSA9ICIiLAogICAgICAgY29sb3IgPSAiR2VucmUiKSArCiAgdGhlbWVfY2xhc3NpYygpCgpnZ3Bsb3RseShnZW5yZV9wb3ApCmBgYAoKVGhlIGdyYXBoIGFib3ZlIHNob3dzIGhvdyB0cmFjayBwb3B1bGFyaXR5IGhhcyB0cmVuZGVkIGJ5IGdlbnJlIHNpbmNlLiBUaG91Z2ggU3BvdGlmeSBoYXMgYSB3aWRlIHZhcmlldHkgb2Ygc29uZ3MsIGJhc2VkIG9uIHRoZSBwbG90IHJvY2sgaXMgdGhlIG9ubHkgZ2VucmUgdGhhdCBoYXMgYW55IHNpZ25pZmljYW50IGZvdW5kYXRpb25zIG9mIHBvcHVsYXIgc29uZ3MgZnJvbSBiZWZvcmUgdGhlIDE5ODBzIGFuZCA5MHMuIFNpbmNlIHRoZW4gaG93ZXZlciwgc29uZyBwb3B1bGFyaXR5IGFjcm9zcyBldmVyeSBnZW5yZSBoYXMgZXhwZXJpZW5jZWQgZXhwb25lbnRpYWwgZ3Jvd3RoIGluIHBvcHVsYXJpdHksIG1vc3Qgbm90YWJseSB3aXRoIHRoZSBpbnRyb2R1Y3Rpb24gb2YgcG9wIGFuZCBlZG0uIEFzIG11c2ljIGJlY29tZXMgZWFzaWVyIHRvIHByb2R1Y2UgYW5kIHJlbGVhc2UgZnJvbSBpbmZvcm1hbCBzZXR0aW5ncywgdG9kYXksIGEgc3R1ZGlvIGFuZCBleHBlbnNpdmUgZXF1aXBtZW50IGFyZSBub3QgbmVjZXNzYXJ5IHRvIG1ha2UgZ29vZCBtdXNpYy4gVGhpcyBpcyBhbHNvIHNob3cgaW4gdGhlIHZpc3VhbGl6YXRpb24gYWJvdmUgd2l0aCB0aGUgcXVhbnRpdHkgb2YgY2FzZXMgZHJhbXRpY2FsbHkgaW5jcmVhc2luZyB3aXRoIHRlaCBhZHZlbnQgb2YgdGVoIDIxc3QgY2VudHVyeS4KCgojIyBIb3cgZG9lcyBkb2VzIHNvbmcgcG9wdWxhcml0eSB2YXJ5IGJhc2VkIG9uIGdlbnJlPwoKYGBge3J9CnByZWxpbV9ncmFwaCA8LSBzcG90aWZ5ICU+JQogIGdncGxvdChhZXMoeSA9IHBsYXlsaXN0X2dlbnJlLCB4ID0gdHJhY2tfcG9wdWxhcml0eSkpICsKICBsYWJzKHRpdGxlID0gIlNvbmcgUG9wdWxhcml0eSBieSBHZW5yZSIsCiAgICAgICB4ID0gIiIsIHkgPSAiIiwKICAgICAgIHN1YnRpdGxlID0gIlNvbmcgcG9wdWxhcml0eSBpcyBtZWFzdXJlZCBmcm9tIDAtMTAwLCB3aXRoIGhpZ2hlciBudW1iZXJzIGJlaW5nIGluZGljaWF0aXZlIG9mIG1vcmUgcG9wdWxhcml0eS5cbkhpZ2hlc3QgbWVkaWFuIHBvcHVsYXJpdGllcyBiZWxvbmcgdG8gcG9wIGFuZCBsYXRpbiB3aXRoIGFuIG92ZXJhbGwgbWVkaWFuIHBvcHVsYXJpdHkgb2YgNDAiLAogICAgICAgY2FwdGlvbiA9ICJBbGV4IElzbWFpbCwgTWFsZWsgS2Fsb3RpLCBCcmlhbiBMZWUiKSArCiAgdGhlbWVfY2xhc3NpYygpICsgCiAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IiwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGZhY2UgPSAiaXRhbGljIikpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lZGlhbih0cmFja19wb3B1bGFyaXR5LCBuYS5ybSA9IFRSVUUpKSwgY29sb3IgPSAiYmx1ZSIpIAoKcHJlbGltX2dyYXBoCmBgYAoKVGhlIGJveCBwbG90IGFib3ZlIGNvbXBhcmVzIGRpc3RyaWJ1dGlvbiBvZiBzb25nIHBvcHVsYXJpdHkgYnkgZ2VucmUgYWdhaW4sIGhvd2V2ZXIgdGhpcyB0aW1lIGluY2x1ZGluZyB0aGUgc29uZ3Mgbm90IGRlZW1lZCBwb3B1bGFyLiBFRE0gbXVzaWMgaXMgbm90aWNlYWJseSBiZWhpbmQgaW4gbWVkaWFuIHBvcHVsYXJpdHkgY29tcGFyZWQgdG8gdGhlIHVuaXZlcnNhbCBtZWRpYW4gb2YgfjQwLCB3aGlsZSBwb3AsIGxhdGluLCBhbmQgdG8gbGVzc2VyIGRlZ3JlZSByYXAgc2hvdyBhIHNsaWdodCBhZHZhbnRhZ2Ugb3ZlciB0aGUgb3RoZXIgZ2VucmVzIGluIG1lZGlhbi4KCgojIEFuYWx5c2lzOiBEaXZpbmcgZGVlcGVyIGludG8gb3VyIGZhdm9yaXRlIGdlbnJlcwoKIyMgUmFwCgpSYXAgaXMgYSBwYXJ0aWN1bGFybHkgZmFzY2luYXRpbmcgZ2VucmUgdG8gaW52ZXN0aWdhdGUgdXNpbmcgdGhlIFNwb3RpZnkgZGF0YSB0byBsb29rIGF0IHdoYXQgdHJhaXRzIG9mIG11c2ljIGhhdmUgY29ycmVsYXRlZCB3aXRoIHBvcHVsYXJpdHkgYXMgdGhlIGdlbnJlIGhhcyB1bmRlcmdvbmUgc2V2ZXJhbCBjaGFuZ2VzIGluIGF1ZGllbmNlIGFuZCBzdHlsZS4gVGhvdWdoIGEgcmVsYXRpdmVseSBuZXcgZ2VucmUgYXJyaXZpbmcgb24gdGhlIGdyZWF0ZXIgbXVzaWMgc2NlbmUgaW4gdGhlIDgwcywgcmFwIGhhcyB1bmRlcmdvbmUgYSBteXJpYWQgb2YgdHJlbmRzIGFuZCBzdHlsZSB2YXJpYXRpb25zLiBGYW5zIG9mIG9sZCBzY2hvb2wgcmFwIGZyb20gdGhlIDgwcyBhbmQgOTBzIG1heSBoYXZlIGRpc3Rhc3RlIGZvciB0b2RheSdzIGFydGlzdHMgbGlrZSBEcmFrZSBhbmQgRW1pbmVtIGZvciBoYXZpbmcgbW9kZXJuaXplZCB0aGUgZ2VucmUgdG9vIG11Y2guIEZhbnMgb2YgbW9kZXJuIHJhcCBtYXkgZ2V0IGJvcmVkIG9mIHRoZSBhdXRoZW50aWMgc291bmQgb2YgYXJ0aXN0cyBsaWtlIFJ1bi1ETUMgb3IgVHVwYWMuIEFyZSB0aGVyZSB0cmVuZHMgdGhhdCB0aWUgYWxsIG9mIHJhcCB0b2dldGhlciBhcyB0byB3aGF0IG1ha2VzIGEgc29uZyBwb3B1bGFyPyAKCiMjIyBTb25nIFF1YWxpdHkKClRoZSBmaXJzdCBhbmQgbW9zdCBuYXR1cmFsIG9ic2VydmF0aW9ucyB0byBtYWtlIGFyZSBvbiBvdmVyYXJjaGluZyBtZXRyaWNzIHRoYXQgU3BvdGlmeSBwcm92aWRlcy4gVXNpbmcgdGhlIGRlc2NyaXB0aW9ucyBwcm92aWRlZCwgSSB3YXMgbW9zdCBpbnRlcmVzdGVkIG9uIHRoZSBmb2xsb3dpbmcgdmFsdWVzIGluIGNvcnJlbGF0aW9uIHRvIHRyYWNrIHBvcHVsYXJpdHk6IERhbmNlYWJpbGl0eSBkdWUgdG8gcmFwJ3MgaGVhdnkgZW1waGFzaXMgb24gcmh5dGhtIGFuZCBiZWF0cywgRW5lcmd5IGR1ZSB0byBzb21lIGFydGlzdHMnIHNpZ25hdHVyZSBzdHlsZSBvZiBzaG91dGluZyB0byAiaHlwZSIgdXAgYSBjcm93ZCAoaWUuIExpbCBKb24sIERNWCksIHRoZSBpbnZlcnNlIHZhcmlhYmxlcyBvZiBTcGVlY2hpbmVzcy9JbnN0cnVtZW50YWxuZXNzIGR1ZSB0byBvdGhlciBhcnRpc3QncyBzaWduYXR1cmUgb2YgcmFwcGluZyBhcyBmYXN0IGFzIHBvc3NpYmxlIChpZS4gRW1pbmVtLCBCdXN0YSBSaHltZXMpLCBhbmQgVmFsZW5jZSBmb3IgdGhlIHBlcmNlaXZlZCBhc3NvY2lhdGlvbiBiZXR3ZWVuIHJhcCBhbmQgdmlvbGVuY2UsIGRydWdzLCBhbmQgZm9jdXMgb24gb3RoZXIgbGVzcy10aGFuLXJpZ2h0ZW91cyB0b3BpY3MuCgpgYGB7ciwgZWNobz1GQUxTRX0Kc3BvdGlmeV9yYXAgJT4lIAogIG11dGF0ZShSb3VuZGVkX0RhbmNlYWJpbGl0eSA9IHJvdW5kKGRhbmNlYWJpbGl0eSwgZGlnaXRzID0gMSksCiAgICAgICAgIFJvdW5kZWRfRW5lcmd5ID0gcm91bmQoZW5lcmd5LCBkaWdpdHMgPSAxKSwKICAgICAgICAgUm91bmRlZF9TcGVlY2hpbmVzcyA9IHJvdW5kKHNwZWVjaGluZXNzLCBkaWdpdHMgPSAxKSwKICAgICAgICAgUm91bmRlZF9JbnN0cnVtZW50YWwgPSByb3VuZChpbnN0cnVtZW50YWxuZXNzLCBkaWdpdHMgPSAxKSwKICAgICAgICAgUm91bmRlZF9WYWxlbmNlID0gcm91bmQodmFsZW5jZSwgZGlnaXRzID0gMSksCiAgICAgICAgIHBvcHVsYXIgPSB0cmFja19wb3B1bGFyaXR5ID4gNzUpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IHN0YXJ0c193aXRoKCJSb3VuZGVkIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlN0YXQxIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlJvdW5kZWRfVmFsdWUiKSAlPiUgCiAgZ3JvdXBfYnkoU3RhdDEsIFJvdW5kZWRfVmFsdWUpICU+JSAKICBzdW1tYXJpemUoUG9wX1JhdGUgPSBtZWFuKHBvcHVsYXIpKjEwMCkgJT4lIAogIG11dGF0ZShTdGF0ID0gZmN0X3JlY29kZShTdGF0MSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGFuY2VhYmlsaXR5ID0gIlJvdW5kZWRfRGFuY2VhYmlsaXR5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFbmVyZ3kgPSAiUm91bmRlZF9FbmVyZ3kiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNwZWVjaGluZXNzID0gIlJvdW5kZWRfU3BlZWNoaW5lc3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEluc3RydW1lbnRhbCA9ICJSb3VuZGVkX0luc3RydW1lbnRhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVmFsZW5jZSA9ICJSb3VuZGVkX1ZhbGVuY2UiKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IFJvdW5kZWRfVmFsdWUsIHkgPSBQb3BfUmF0ZSkpICsKICBnZW9tX2xpbmUoYWVzKGNvbG9yID0gU3RhdCkpICsKICBsYWJzKHRpdGxlID0gIlBvcHVsYXJpdHkgb2YgUmFwIFNvbmdzIGJ5IFNvbmcgQ2hhcmFjdGVyaXN0aWMiLAogICAgICAgeCA9ICIiLCB5ID0gIlBlcmNlbnQgUG9wdWxhciIsIGNvbG9yID0gIlNvbmcgU3RhdGlzdGljIikgKwogIHRoZW1lX2NsYXNzaWMoKSArIAogIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGxvdCIsCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBmYWNlID0gIml0YWxpYyIpKQpgYGAKCk9kZGx5LCB0aGUgYmlnZ2VzdCBjb25jbHVzaW9uIEkgZHJldyBmcm9tIHRoaXMgZ3JhcGggd2FzIG5vdCBhbnkgcG9zaXRpdmUgb3IgbmVnYXRpdmUgY29ycmVsYXRpb24sIGJ1dCBhIGxhY2sgb2YgY29ubmVjdGlvbiBiZXR3ZWVuIHZhbGVuY2UgYW5kIHBvcHVsYXJpdHkuIEZvciBhIGdlbnJlIHRoYXQgaGFzIGEgcmVwdXRhdGlvbiBmb3IgYmVpbmcgY29ubmVjdGVkIHdpdGggZ2FuZ3MsIGd1bnMsIGRydWdzLCBldGMuLCB0aGVyZSBpcyBhIGNvbXBsZXRlIGxhY2sgb2YgY29ycmVsYXRpb24gYmV0d2VlbiB2YWxlbmNlIGFuZCBwb3B1bGFyaXR5LiBCZXlvbmQgdGhhdCwgdGhlcmUgaXMgYSBtb2RlcmF0ZWx5IHN0cm9uZyBjb3JyZWxhdGlvbiBiZXR3ZWVuIHBvcHVsYXJpdHkgYW5kIGRhbmNlYWJpbGl0eSwgYXMgSSBoYWQgZXhwZWN0ZWQgYmFzZWQgb24gdGhlIHByZXZhbGVuY2Ugb2YgYmVhdHMgYW5kIHJoeXRobXMgaW4gcmFwLiBUaGUgZW5lcmd5IGxpbmUgc2hvd3MgdGhhdCB0aGUgaGlnaGVzdCBwZXJjZW50YWdlIG9mIHNvbmdzIHRvIGJlY29tZSBwb3B1bGFyIGFyZSB+LjUgZW5lcmd5LCB3aGljaCBsaWtlbHkgc3VnZ2VzdHMgdG9vIG11Y2ggZW5lcmd5IGNhbiB0YWtlIGF3YXkgZnJvbSB0aGUgcG9wdWxhcml0eSBvZiBhIHNvbmcuIEZpbmFsbHksIHRoZSBzcGVlY2hpbmVzcy9pbnN0cnVtZW50YWxuZXNzIHZhcmlhYmxlIHNob3dzIHRoYXQgc29uZ3Mgb24gdGhlIGV4dHJlbWUgZW5kIG9mIHNwZWVjaGluZXNzICguOCspIGFyZSBtb3N0IGxpa2VseSB0byBiZSBwb3B1bGFyLgoKIyMjIERvIHNvbmdzIHdpdGggbXVsdGlwbGUgYXJ0aXN0cyBiZWNvbWUgcG9wdWxhciBhdCBhIGhpZ2hlciByYXRlPwoKQmV5b25kIHRoZSBzdGF0cywgdGhlcmUgd2FzIG9uZSBtb3JlIG9ic2VydmF0aW9uIEkgd2FudGVkIHRvIG1ha2Ugb24gcmFwIG11c2ljLiBCYXNlZCBvbiBteSBleHBlcmllbmNlIGxpc3RlbmluZyB0byByYXAsIHNvbWUgb2YgbXkgZmF2b3JpdGUgc29uZ3MgYXJlIHJlbWl4ZXMsIGZlYXR1cmVzLCBvciBhbnkgb3RoZXIgd2F5IG11bHRpcGxlIGFydGlzdHMgY2FuIHB1dCB2ZXJzZXMgb24gdGhlIHNhbWUgc29uZy4gU29uZ3MgbGlrZSAiTGlmZSBpcyBHb29kIiBieSBEcmFrZSBhbmQgRnV0dXJlLCBvciByZW1peGVzIHRvIHNvbmdzIGxpa2UgIkhJR0hFU1QgSU4gVEhFIFJPT00iIHdoaWNoIGluY29ycG9yYXRlcyBMaWwgQmFieSBpbiBhIHNvbmcgYnkgVHJhdmlzIFNjb3R0IGFkZCBhIGNlcnRhaW4gbGV2ZWwgb2YgZnJlc2huZXNzIGFuZCBicmVhayB1cCB0aHJlZSBjb25zZWN1dGl2ZSBtaW51dGVzIG9mIG9uZSBhcnRpc3QgcmFwcGluZyBpbnRvIGZ1biBiYWNrIGFuZCBmb3J0aHMgd2l0aCBzdHlsZXMuIEJlbG93IGlzIGEgZ3JhcGhpYyBjb21wYXJpbmcgdGhlIHBvcHVsYXJpdHkgcmF0ZXMgb2YgdGhvc2Ugc29uZ3MgdnMgc29sbyBzb25ncyBiZXR3ZWVuIHJhcCBhbmQgb3RoZXIgZ2VucmVzLgoKYGBge3IgZmlnLndpZHRoID0gOSwgZmlnLmxlbmd0aCA9IDZ9Ck11bHRpcGxlX0FydGlzdF9HcmFwaCA8LSBzcG90aWZ5ICU+JSAKICBtdXRhdGUodHJhY2tfbmFtZV9sb3dlciA9IHN0cl90b19sb3dlcih0cmFja19uYW1lKSwKICAgICAgICAgcmVtaXggPSBzdHJfZGV0ZWN0KHRyYWNrX25hbWVfbG93ZXIsICJSZW1peCIpLAogICAgICAgICBmZWF0dXJlID0gc3RyX2RldGVjdCh0cmFja19uYW1lX2xvd2VyLCAiZmVhdCIpLAogICAgICAgICBtYV9wcmVwID0gcmVtaXh8ZmVhdHVyZSwKICAgICAgICAgbWFfcHJlcDIgPSByZXBsYWNlX25hKG1hX3ByZXAsIEZBTFNFKSwKICAgICAgICAgbXVsdGlwbGVfYXJ0aXN0cyA9IGlmX2Vsc2UobWFfcHJlcDIsIHRydWUgPSAiTXVsdGlwbGUgQXJ0aXN0cyIsIGZhbHNlID0gIk9uZSBBcnRpc3QiKSwKICAgICAgICAgcG9wdWxhciA9IHRyYWNrX3BvcHVsYXJpdHkgPiA3NSkgJT4lIAogIGdyb3VwX2J5KG11bHRpcGxlX2FydGlzdHMsIHBsYXlsaXN0X2dlbnJlKSAlPiUgCiAgc3VtbWFyaXplKHByb3BfcG9wID0gbWVhbihwb3B1bGFyKSoxMDApICU+JSAKICBtdXRhdGUoZ2VucmUgPSBmY3RfcmVsZXZlbChwbGF5bGlzdF9nZW5yZSwgInJhcCIpKSAlPiUgCiAgZ2dwbG90KCkgKwogIGdlb21fY29sKGFlcyh4ID0gbXVsdGlwbGVfYXJ0aXN0cywgeSA9IHByb3BfcG9wKSwgZmlsbCA9ICJibGFjayIpICsKICBmYWNldF93cmFwKH5nZW5yZSkgKwogIGxhYnModGl0bGUgPSAiUG9wdWxhcml0eSBvZiBTb25ncyBDb250YWluaW5nIE11bGl0cGxlIEFydGlzdHMgQWNyb3NzIEdlbnJlIiwKICAgICAgIHggPSAiIiwgeSA9ICJQZXJjZW50IG9mIFNvbmdzIFBvcHVsYXIiKSArCiAgdGhlbWVfY2xhc3NpYygpICsgCiAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IiwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGZhY2UgPSAiaXRhbGljIikpCgpnZ3Bsb3RseShNdWx0aXBsZV9BcnRpc3RfR3JhcGgpCmBgYAoKUmFwIGhhZCB0aGUgbGFyZ2VzdCBjaGFuZ2UgYmV0d2VlbiBzb25ncyB3aXRoIG11bHRpcGxlIGFydGlzdHMgYW5kIHNvbmcgd2l0aCBvbmx5IG9uZSwgd2l0aCBhIGdhcCBvZiAxMCUuIEJhc2VkIG9uIG90aGVyIGdlbnJlcycgZGlzcGFyaXR5IGxpa2UgUiZCIGFuZCBwb3AsIEkgaHlwb3RoZXNpemUgdGhhdCB0aGVzZSB0cmVuZHMgYXJlIGNvbm5lY3RlZCB3aXRoIHRoZSBtb2Rlcm4gZGF5IG11c2ljIHNjZW5lLiBDb2xsYWJvcmF0aW9uIGJldHdlZW4gYXJ0aXN0cyBhdCB0aGUgdG9wIG9mIHRoZWlyIGZpZWxkIGhhcyBiZWNvbWUgbW9yZSBjb21tb25wbGFjZSwgZXZlbiB3aXRoIHNvbWUgbWVnYS10cmFja3MgbGlrZSAiRm9yZXZlciIgd2l0aCB2ZXJzZXMgZnJvbSBFbWluZW0sIEthbnllIFdlc3QsIERyYWtlLCBhbmQgTGlsIFdheW5lIGFsbCBpbiB0aGUgc2FtZSBzb25nLiBUaGVzZSBjb2xsYWJvcmF0aW9ucyBjYW4gY3JlYXRlIHNvbmdzIHdpdGggYmxlbmRlZCBzdHlsZXMsIHdoaWNoIGV2ZW4gZnVydGhlcnMgdGhlIGRldmVsb3BtZW50IG9mIHJhcCBhcyBhIHVuaXF1ZSBnZW5yZS4KCgoKIyMgUiZCCgojIyMgV2h5IFImQj8KCkluIHRoaXMgc2VjdGlvbiwgSSB3YW50IHRvIHRha2UgYSBjbG9zZXIgbG9vayBhdCBvbmUgb2YgbXkgZmF2b3JpdGUgZ2VucmVzIG9mIG11c2ljLCBSJkIuIEkgdGhpbmsgSSBsb3ZlIGl0IHNvIG11Y2ggYmVjYXVzZSBpdCdzIG9mdGVuIGdvb2QgbXVzaWMgdG8gdW53aW5kIHRvIC0tIGl0J3Mgc21vb3RoLCBzbG93LCBhbmQgcmVsYXhpbmcuIEkgYWxzbyBsb3ZlIGl0cyB2ZXJzYXRpbGl0eSEgUiZCIGNhbiBmaXQgdGhlIG1vb2Qgb2YgYW55dGhpbmcgZnJvbSBhIGdsb29teSwgcmFpbnkgZGF5IHRvIGEgYnJpZ2h0LCBzdW5ueSBkYXkuIEJ1dCB3aHk/IFdoYXQgY2hhcmFjdGVyaXN0aWNzIG1ha2UgUiZCIHN1Y2ggYSBncmVhdCBnZW5yZSB0byBsaXN0ZW4gdG8/IFVzaW5nIHRoZSBTcG90aWZ5IGRhdGFzZXQgYW5kIHNvbWUgdmlzdWFsaXphdGlvbnMgd2hpY2ggbG9vayBhdCB0aGUgc3BlY2lmaWMgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBtb3N0IHBvcHVsYXIgUiZCIHNvbmdzIChzb25ncyB3aXRoIGEgcG9wdWxhcml0eSByYXRpbmcgb2YgYWJvdmUgNzUpLCBJIGhvcGUgdG8gY29tZSBjbG9zZXIgdG8gYW5zd2VyaW5nIHRoZXNlIHF1ZXN0aW9ucy4KCmBgYHtyfQpyYW5kYiAlPiUKICBzZWxlY3QodHJhY2tfbmFtZSwgdHJhY2tfYXJ0aXN0LCBwbGF5bGlzdF9nZW5yZSwgcGxheWxpc3Rfc3ViZ2VucmUsIHRyYWNrX3BvcHVsYXJpdHksIGRhbmNlYWJpbGl0eSwgZW5lcmd5LCBsb3VkbmVzcywgbW9kZSwgc3BlZWNoaW5lc3MsIGFjb3VzdGljbmVzcywgaW5zdHJ1bWVudGFsbmVzcywgbGl2ZW5lc3MsIHZhbGVuY2UsIGR1cmF0aW9uX21zKSAlPiUKICBhcnJhbmdlKGRlc2ModHJhY2tfcG9wdWxhcml0eSkpICU+JQogIGhlYWQoMTIpICU+JQogIGtuaXRyOjprYWJsZSgpIApgYGAKCkFib3ZlIGFyZSB0aGUgdG9wIDEwIG1vc3QgcG9wdWxhciBzb25ncyBpbiB0aGUgUiZCIGdlbnJlICgxMiBzb25ncyB3ZXJlIHB1bGxlZCBmcm9tIHRoZSBkYXRhc2V0IHRvIGFjY291bnQgZm9yIDIgc29uZ3MgdGhhdCB3ZXJlIGVhY2ggaW4gMiBkaWZmZXJlbnQgc3ViZ2VucmVzIC0tIEFyaXpvbmEgWmVyYXZhcycgKlJveGFubmUqIGFuZCBUaGUgV2Vla25kJ3MgKkJsaW5kaW5nIExpZ2h0cyouIFdlIGNhbiBzZWUgdGhhdCBhbGwgb2YgdGhlbSB3ZXJlIHJlbGVhc2VkIGluIDIwMTkgYW5kIGFsbCBjYXRlZ29yaXplZCB1bmRlciBteSB0d28gZmF2b3JpdGUgdHdvIHN1YmdlbnJlcyBvZiBSJkIsIFVyYmFuIENvbnRlbXBvcmFyeSBhbmQgSGlwIFBvcC4gQWxsIG9mIHRoZW0gYWxzbyBib2FzdCBhIGRhbmNlYWJpbGl0eSBzY29yZSBvZiBhYm92ZSAwLjUsIHdpdGggbW9zdCBvZiB0aGVtICh3aXRoIHRoZSBleGNlcHRpb24gb2YgTWFyb29uIDUncyAqTWVtb3JpZXMqIGFuZCBCaWxsaWUgRWlsaXNoJ3MgKmV2ZXJ5dGhpbmcgaSB3YW50ZWQqKSBoYXZpbmcgZW5lcmd5IHNjb3JlcyBvZiBhYm92ZSAwLjUuIFdlIGNhbiBhbHNvIHNlZSB0aGF0IGFjcm9zcyB0aGUgYm9hcmQsIGFsbCAxMCBzb25ncyBoYXZlIGxvdyBzcGVlY2hpbmVzcyBhbmQgaW5zdHJ1bWVudGFsbmVzcyBzY29yZXMgKHdpdGggdGhlIGV4Y2VwdGlvbiBvZiBCaWxsaWUgRWlsaXNoJ3MgKmV2ZXJ5dGhpbmcgaSB3YW50ZWQqLiBJbnRlcmVzdGluZ2x5LCBhbGwgb2YgdGhlIHNvbmdzIGZhbGwgd2l0aGluIGEgdmFsZW5jZSBvZiAwLjItMC42LiBUaGUgb3RoZXIgY2hhcmFjdGVyaXN0aWNzIGFyZSBxdWl0ZSB2YXJpZWQuIFNvLCBmb3IgdGhlIHB1cnBvc2VzIG9mIG15IGFuYWx5c2lzIG9mIHRoZSBSJkIgZ2VucmUsIEkgd2lsbCBvbmx5IGZvY3VzIG9uIHRoZSBzb25nIGNoYXJhY3RlcmlzdGljcyB0aGF0IGhhdmUgY2xlYXIgdHJlbmRzIGFjcm9zcyB0aGUgZ2VucmUgLS0gZGFuY2VhYmlpbGl0eSwgZW5lcmd5LCBzcGVlY2hpbmVzcywgaW5zdHJ1bWVudGFsbmVzcywgYW5kIHZhbGVuY2UuCgojIyMgV2hpY2ggc3ViZ2VucmVzIGhhdmUgdGhlIG1vc3QgcG9wdWxhciBzb25ncz8KCkluIHRoZSBleHBsb3JhdG9yeSBwaGFzZSBvZiBteSBhbmFseXNpcyBvZiB0aGUgUiZCIGdlbnJlLCB0aGUgbW9zdCBvYnZpb3VzIGNoYXJhY3RlcmlzdGljIG9mIGEgc29uZyBpbiB0aGUgUiZCIGdlbnJlIHdhcyBhIHNvbmcncyBzdWJnZW5yZS4gQXJlIGNlcnRhaW4gZ2VucmVzIG1vcmUgbGlrZWx5IHRvIGhhdmUgbW9yZSBwb3B1bGFyIHNvbmdzIGJlY2F1c2Ugc29tZSBoYXZlIG1vcmUgZmFucyBhbmQgbGlzdGVuZXJzIHRoYW4gb3RoZXJzPyBJbiB0aGUgZGVuc2l0eSBwbG90IGJlbG93LCB3ZSBzZWUgdGhhdCB0aGlzIGlzIHRoZSBjYXNlIC0tIE5lby1Tb3VsIGFuZCBOZXcgSmFjayBTd2luZyBoYXZlIHRoZSBoaWdoZXN0IHF1YW50aXR5IG9mIHBvcHVsYXIgc29uZ3MuIAoKYGBge3IgZmlnLndpZHRoID0gNywgZmlnLmxlbmd0aCA9IDUsIGV2YWwgPSBGQUxTRX0KcmFuZGIgJT4lIAogIGdncGxvdChhZXMoeCA9IHRyYWNrX3BvcHVsYXJpdHksIGZpbGwgPSBwbGF5bGlzdF9zdWJnZW5yZSkpICsKICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjEpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxhYnModGl0bGUgPSAiRG8gY2VydGFpbiBzdWJnZW5yZXMgaGF2ZSBtb3JlIHBvcHVsYXIgc29uZ3M/IiwKICAgICAgIHN1YnRpdGxlID0gIlRoaXMgZGVuc2l0eSBwbG90IG9ubHkgaW5jbHVkZXMgc29uZ3Mgd2l0aCBhIHBvcHVsYXJpdHkgb2YgPj03NS5cbkl0IHNlZW1zIHRoYXQgTmVvLVNvdWwgYW5kIE5ldyBKYWNrIFN3aW5nIGhhdmUgdGhlIG1vc3QgcG9wdWxhciBzb25ncy5cblxuUiZCIFN1YmdlbnJlOiB7Y2xvc2VzdF9zdGF0ZX0iLAogICAgICAgeCA9ICJUcmFjayBQb3B1bGFyaXR5IiwKICAgICAgIHkgPSAiIiwKICAgICAgIGZpbGwgPSAiUiZCIHN1YmdlbnJlIiwKICAgICAgIGNhcHRpb24gPSAiVmlzdWFsaXphdGlvbiBjcmVhdGVkIGJ5IEJyaWFuIExlZSIpICsKICB0cmFuc2l0aW9uX3N0YXRlcyhwbGF5bGlzdF9zdWJnZW5yZSwgdHJhbnNpdGlvbl9sZW5ndGggPSAzLCBzdGF0ZV9sZW5ndGggPSAxKQojZ2V0IHJpZCBvZiBheGVzLCBtYWtlIHN1YnRpdGxlIGRlc2NyaXB0aXZlCmFuaW1fc2F2ZSgicmFuZGJfZGVuc2l0eS5naWYiKQpgYGAKCmBgYHtyfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygicmFuZGJfZGVuc2l0eS5naWYiKQpgYGAKCkluIHRoZSBkZW5zaXR5IHBsb3QgYWJvdmUsIE5lby1Tb3VsIGFuZCBOZXcgSmFjayBTd2luZyBib3RoIHNlZW0gdG8gaGF2ZSBhIGxvdCBvZiBwb3B1bGFyIHNvbmdzIG9uIHRoZSBsb3dlciBlbmQgb2YgdGhlIHNwZWN0cnVtICg3NS04NSksIHdpdGggVXJiYW4gQ29udGVtcG9yYXJ5IGFuZCBIaXAgUG9wIGZvbGxvd2luZyBzaW1pbGFyIHRyZW5kcywgYnV0IGluIGNvbXBhcmlzb24gdG8gdGhlIG90aGVyIHR3byBnZW5yZXMsIHRoZWlyIGRlbnNpdHkgY3VydmVzIGFyZSBub3QgYXMgbGFyZ2UsIHNpZ25hbGluZyB0aGF0IHRoZSBmb3JtZXIgdHdvIGdlbnJlcyBoYXZlIG1vcmUgc29uZ3MgY2xhc3NpZmllZCBhcyAicG9wdWxhciIgdGhhbiB0ZWggbGF0dGVyIHR3by4KCkkgYmVsaWV2ZSB0aGF0IHRoaXMgdHJlbmQgY291bGQgYmUgb2NjdXJyaW5nIGJlY2F1c2Ugb2YgdGhlIGh1Z2UgaW5jcmVhc2UgaW4gdGhlIHByb2R1Y3Rpb24gb2YgaGlwIHBvcCBhbmQgdXJiYW4gY29udGVtcG9yYXJ5IG11c2ljLiBXaXRoIHN0cmVhbWluZyBzZXJ2aWNlcyBzdWNoIGFzIFNwb3RpZnkgbWFraW5nIGl0IGVhc2llciB0aGFuIGV2ZXIgZm9yIHNtYWxsIGNyZWF0b3JzIHRvIGF0dGFpbiBwbGF0Zm9ybXMgYW5kIHdpdGggdGhlIGFkdmFuY2VtZW50IG9mIHRlY2hub2xvZ3kgbWFraW5nIGl0IGVhc2llciB0byBwcm9kdWNlIGFuZCByZWxlYXNlIG11c2ljIGZyb20gb25lJ3Mgb3duIGJlZHJvb20sIHRoaXMgbWF5IGJlIGJlY2F1c2Ugb2YgdGhlIG92ZXJzYXR1cmF0aW9uIG9mIHRoZSBtdXNpYyBpbmR1c3RyeSAtLSB0aGVyZSBhcmUgbW9yZSBzb25ncyBiZWluZyByZWxlYXNlZCB0aGFuIGV2ZXIuCgpgYGB7cn0KcmFuZGIgJT4lCiAgZ3JvdXBfYnkocGxheWxpc3Rfc3ViZ2VucmUpICU+JQogIHN1bW1hcml6ZShudW1fb2Zfc29uZ3MgPSBuKCksIGF2Z19wb3AgPSBtZWFuKHRyYWNrX3BvcHVsYXJpdHkpKSAlPiUKICBrbml0cjo6a2FibGUoKSAKYGBgCgpEZXNwaXRlIHRoZSBsYXJnZSBkZW5zaXR5IGN1cnZlcywgb24gYXZlcmFnZSwgaGlwIHBvcCBhbmQgdXJiYW4gY29udGVtcG9yYXJ5IGFyZSBzbGlnaHRseSBtb3JlIHBvcHVsYXIgdGhhbiB0aGUgTmVvLVNvdWwgYW5kIE5ldyBKYWNrIFN3aW5nLiBBbm90aGVyIGludGVyZXN0aW5nIG9ic2VydmF0aW9uIHdlIGNhbiBtYWtlIGlzIHRoZSBzaGVlciBsYWNrIG9mIHBvcHVsYXIgc29uZ3MgZm9yIE5lby1Tb3VsIGFuZCBOZXcgSmFjayBTd2luZy4gCgpBIHF1aWNrIEdvb2dsZSBzZWFyY2ggd2lsbCByZXZlYWwgdGhhdCBib3RoIE5lby1Tb3VsIGFuZCBOZXcgSmFjayBTd2luZyB3ZXJlIHN1YmdlbnJlcyBvZiBSJkIgdGhhdCB3ZXJlIHBvcHVsYXIgZHVyaW5nIHRoZSAxOTgwJ3MvOTAncy4gVGhlaXIgbGFyZ2UgZGVuc2l0eSBjdXJ2ZXMgY291bGQgYmUgZHVlIHRvIHRoaXMgZmFjdC4gQmVjYXVzZSB0aGUgdGVjaG5vbG9neSBmb3IgaG91c2Vob2xkIGhpZ2ggcXVhbGl0eSBoYW5kaGVsZCBtaWNyb3Bob25lcyBhbmQgcHJvZHVjaW5nIGVxdWlwbWVudCB3YXMgbm90IGluIGFidW5kYW5jZSBsaWtlIGl0IGlzIG5vdywgYXJ0aXN0cyBoYWQgdG8gcmVseSBvbiBsYWJlbCBjb21wYW5pZXMgYW5kIG1hbmFnZXJzIGZvciB0aGUgZnVuZGluZyB0byBhY3F1aXJlIHRoZSBtb25leSBmb3Igc3R1ZGlvcyBhbmQgZXhwZW5zaXZlIGVxdWlwbWVudCwgdGh1cyBsZWFkaW5nIHRvIGxlc3MgbXVzaWMgYmVpbmcgcHJvZHVjZWQuIEFkZGl0aW9uYWxseSwgYmVjYXVzZSBsYWJlbGluZyBhZ2VuY2llcyBhbmQgbWFuYWdlcmlhbCBhZ2VuY2llcyBlc3NlbnRpYWxseSAiaW52ZXN0ZWQiIGluIGRpc2NvdmVyZWQgYXJ0aXN0cyB3aG9tIHRoZXkga25ldyB0aGV5IHdvdWxkIGdldCBhIGhpZ2ggcHJvZml0IG1hcmdpbiBmcm9tLCB0aGUgZGlzY292ZXJlZCBhcnRpc3RzIHdobyB3ZXJlIGdpdmVuIGEgcGxhdGZvcm0gYnkgdGhlc2UgYWdlbmNpZXMgd2VyZSBtb3JlIGxpa2VseSB0byBiZSBzdWNjZXNzZnVsLiBXaXRoIGEgc21hbGxlciBwb29sIG9mIG11c2ljIGFuZCBtb3JlIHBvcHVsYXIgc29uZ3MgbWFraW5nIHVwIHRoYXQgc21hbGwgcG9vb2wgb2YgbXVzaWMsIGxhcmdlIGRlbnNpdHkgY3VydmVzIHN1Y2ggYXMgdGhlIG9uZXMgd2Ugc2VlIGluIHRoZSB2aXN1YWxpemF0aW9uIGFib3ZlIGZvciBOZW8tU291bCBhbmQgTmV3IEphY2sgU3dpbmcgYXJlIHBvc3NpYmxlLCBhbmQgY291bGQgc2VydmUgYXMgYW4gZXhwbGFuYXRpb24gZm9yIHRoZSBkaWZmZXJlbmNlIGluIHRoZSBxdWFudGl0eSBiZXR3ZWVuIHRoZSBmb3VyIGdlbnJlcy4KCkFzIEkgbW92ZSBmb3J3YXJkIGluIG15IGFuYWx5c2lzIHRvIGxvb2sgYXQgdGhlIHNwZWNpZmljIGNoYXJhY3RlcmlzdGljcyBvZiBwb3B1bGFyIFImQiBzb25ncywgSSB3aWxsIHJlc3RyaWN0IG15c2VsZiB0byB0aGUgdHdvIHN1YmdlbnJlcyB3aXRoIG1vcmUgY2FzZXMgdG8gbG9vayBhdCBhbmQgbXkgcGVyc29uIHR3byBmYXZvcml0ZSBzdWJnZW5yZXMgLS0gSGlwLVBvcCBhbmQgVXJiYW4gQ29udGVtcG9yYXJ5LgoKIyMjIFRha2luZyBhIGNsb3NlciBsb29rIGF0IHRoZSBzcGVjaWZpYyBjaGFyYWN0ZXJpc3RpY3Mgb2YgcG9wdWxhciBzb25ncyBpbiB0aGUgSGlwLVBvcCBhbmQgVXJiYW4gQ29udGVtcG9yYXJ5IFN1YmdlbnJlcwoKYGBge3J9CnJhbmRiMiA8LXJhbmRiICU+JQogIGdyb3VwX2J5KHBsYXlsaXN0X3N1YmdlbnJlKSAlPiUKICBmaWx0ZXIocGxheWxpc3Rfc3ViZ2VucmUgPT0gYygiaGlwIHBvcCIsICJ1cmJhbiBjb250ZW1wb3JhcnkiKSkgJT4lCiAgc3VtbWFyaXNlX2F0KGMoInRyYWNrX3BvcHVsYXJpdHkiLCAiZGFuY2VhYmlsaXR5IiwgImVuZXJneSIsICJzcGVlY2hpbmVzcyIsICJpbnN0cnVtZW50YWxuZXNzIiwgInZhbGVuY2UiKSwgbWVhbiwgbmEucm0gPSBUUlVFKQogICNrbml0cjo6a2FibGUoKSAKYGBgCgpMb29raW5nIGF0IHRoZSB0YWJsZSBhYm92ZSwgd2Ugc2VlIHRoYXQgdGhlIHZhbHVlcyBmb3IgZWFjaCBjaGFyYWN0ZXJpc3RpYyBhcmUgbmVhcmx5IGlkZW50aWNhbCwgb2Z0ZW4ganVzdCAwLjAxIG9mZiBmcm9tIGVhY2ggb3RoZXIuIEFkZGl0aW9uYWxseSwgd2l0aCB0aGUgcG9wdWxhcml0eSBvZiB0aGUgdHdvIHN1YmdlbnJlcyBiZWluZyBzbyBjbG9zZSB0byBlYWNoIG90aGVyLCBpdCdzIHNhZmUgdG8gc2F5IHRoYXQgaGlnaCBkYW5jZWFiaWxpdHksIGVuZXJneSwgYW5kIHZhbGVuY2UgYXJlIHRyYWl0cyB0aGF0IGFyZSBzZWVuIGluIHBvcHVsYXIgc29uZ3Mgb2YgYm90aCBzdWJnZW5yZXMgLS0gSGlwIFBvcCBhbmQgVXJiYW4gQ29udGVtcG9yYXJ5LiBPbiB0aGUgY29udHJhcnksIHBvcHVsYXIgc29uZ3Mgb2YgYm90aCBzdWJnZW5yZXMgYXJlIHNwZWVjaGluZXNzIGFuZCBpbnN0cnVtZW50YWxuZXNzIFRoaXMgZG9lcyBtYWtlIGxvZ2ljYWwgc2Vuc2UsIGFzIFImQiBpcyBvZnRlbiBvbiB0aGUgc2xvd2VyLCBzbW9vdGhlciBzaWRlLCBoZW5jZSB0aGUgbG93IHNwZWVjaGluZXNzIChjb250cmFyeSB0byByYXApLiAKCkZvciBwb3B1bGFyIHNvbmdzIG9mIHRoZSB0d28gc3ViZ2VucmVzIHdoZXJlIGhpZ2ggZGFuY2VhYmlsaXR5LCBlbmVyZ3ksIGFuZCB2YWxlbmNlLCBhcmUgcHJldmFsZW50LCBJIGJlbGlldmUgdGhhdCB0aGlzIGZvbGxvd3MgZ2VuZXJhbCB0cmVuZHMgYWNyb3NzIGdlbnJlcywgd2hlcmUgcGVvcGxlIHdhbnQgdG8gbGlzdGVuIHRvIHVwYmVhdCwgZW5lcmdldGljIG11c2ljIHRoYXQgdGhleSBjYW4gZGFuY2UgdG8uIEFwcGFyZW50bHksIFImQiBsaXN0ZW5lcnMgdGVuZCB0byBiZSBpbiBmYXZvciBvZiBzb25ncyB0aGF0IGhhdmUgdm9jYWwgc2luZ2luZyB3aXRob3V0IG1hbnkgbHlyaWNzIGR1ZSB0byB0aGUgbG93IHNwZWVjaGluZXNzIHZhbHVlIGFuZCBpbnN0cnVtZW50YWxuZXNzIHZhbHVlcyAtLSBzb25ncyB3aXRoIGxvdHMgb2YgIm9vaHMiIGFuZCAiYWhzIiwgYXMgZGVmaW5lZCBieSB0aGUgY29kZWJvb2sgb24gdGhlIHJlcG9zaXRvcnkgcGFnZSB3aGljaCBzYXlzIHRoYXQgdGhlIGNsb3NlciBpbnRydW1lbnRhbG5lc3MgaXMgdG8gMS4wLCB0aGUgZ3JlYXRlciBsaWtlbGlob29kIHRoZSB0cmFjayBjb250YWlucyBubyB2b2NhbCBjb250ZW50LiBJdCBhbHNvIG5vdGVzIHRoYXQg4oCcT29o4oCdIGFuZCDigJxhYWjigJ0gc291bmRzIGFyZSB0cmVhdGVkIGFzIGluc3RydW1lbnRhbCBpbiB0aGlzIGNvbnRleHQuIAoKIyMjIFImQiAtLSBBbmFseXNpcyBDb25jbHVzaW9uCgpBbGwgaW4gYWxsLCBJIGJlbGlldmUgdGhhdCBSJkIgZm9sbG93cyBvdmVyYWxsIHRyZW5kcyBvZiBwb3B1bGFyIG11c2ljIGFjcm9zcyBhbGwgZ2VucmVzLCBhcyBzZWVuIHdpdGggdGhlIGhpZ2ggdmFsdWVzIGZvciBkYW5jZWFiaWxpdHksIHZhbGVuY2UsIGFuZCBlbmVyZ3kuIFRoZSBkZWZpbmluZyBkaWZmZXJlbmNlLCBhbmQgd2hhdCBzZXRzIFImQiBhcGFydCBmcm9tIHRoZSBvdGhlciBnZW5yZXMsIGlzIHRoZSBsb3cgdmFsdWVzIGZvciBpbnN0cnVtZW50YWxuZXNzIGFuZCBzcGVlY2hpbmVzcy4gSSBhbHNvIGRpc2NvdmVyZWQgdGhhdCB3aGF0IEkgbG92ZSBhYm91ciBSJkIgaXMgYWN0dWFsbGx5IHdoYXQgbWFrZXMgaXQgcG9wdWxhciEgSG9wZWZ1bGx5LCB0aGVzZSBkaXNjb3ZlcmllcyBhbmQgbXkgYW5hbHlzaXMgb2YgZ2VucmUncyBjaGFyYWNydGVyaXN0aWNzIHdpbGwgaGVscCBtZSBhbmQgb3RoZXJzIGZpbmQgbW9yZSByZWxldmFudCBSJkIgcmVjb21tZW5kYXRpb25zLgoKIyMgUG9wCgpXaG8gaGFzbid0IGJlZW4gaW4gYSAiYWFhaCwgSSBrbm93IHRoaXMgc29uZyIgbW9tZW50IGJ1dCBkaWRuJ3Qga25vdyB3aGVyZSB0aGV5IGtuZXcgaXQgZnJvbT8gIE9yIGV2ZW4gd29yc2UsIHNpbmdpbmcgdGhlIGx5cmljcyBvZiBhIHNvbmcgeW91IGhhdGUgYmVjYXVzZSB5b3UgY291bGRuJ3QgaGVscCBidXQgbWVtb3JpemUgdGhlbSBzaW5jZSB0aGUgdHJhY2sgd2FzIHBsYXlpbmcgZXZlcnl3aGVyZS4gQ2hhbmNlcyBhcmUsIHlvdSBoZWFyZCB0aGF0IHR1bmUgb24gdGhlIGNhciByYWRpbyB3aGVuIHlvdXIgcGhvbmUncyBiYXR0ZXJ5IGRpZWQgb3IgbWF5YmUgZXZlbiBhdCB0aGUgc3RvcmUgd2hlbiB5b3Ugd2VudCB0byBidXkgYSBjaGFyZ2VyIGZvciB5b3VyIHBob25lLiBUaGVzZSBzb25ncyB0aGF0IHdlIG9mdGVuIGZpbmQgaW1wb3NzaWJsZSB0byBnZXQgb3V0IG9mIG91ciBoZWFkIGFyZSBpbiBtYW55IGNhc2VzIHRvcCBoaXQgc29uZ3M7IGhlbmNlIHRoZSByZWFzb24gdGhleSdyZSBldmVyeXdoZXJlLiBCdXQgd2hhdCBtYWtlcyB0aGVzZSBwb3B1bGFyIHNvbmdzLgoKV2UgY2Fubm90IHRhbGsgYWJvdXQgcG9wdWxhciBtdXNpYyB3aXRob3V0IGNyb3NzaW5nIHBvcCBtdXNpYy4gSW4gZmFjdCwgdGhlIHRlcm1zIHBvcHVsYXIgbXVzaWMgYW5kIHBvcCBtdXNpYyBhcmUgb2Z0ZW4gdXNlZCBpbnRlcmNoYW5nZWFibHkuIFRoaXMgZ2VucmUgaGFzIGEgZm9ybXVsYSB0aGF0IGNoYXJnZXMgdXAgb3VyIGFkcmVuYWxpbmUgbGV2ZWxzIGFuZCBnaXZlIHVzIG5vIGNob2ljZSBidXQgdG8gZGFuY2UgdG8gdGhlIGJlYXQsIGV2ZW4gaWYgaXQgd2FzIG9ubHkgYSBjb3VwbGUgb2Ygc2hvdWxkZXIgc2hydWdzLiBJIHBlcnNvbmFsbHkgZmluZCBteXNlbGYgaGVscGxlc3MgdG8gYSBnb29kIHBvcCBiZWF0LiBOZXZlcnRoZWxlc3MsIG5vdCBhbGwgcG9wIG11c2ljIGdpdmUgdXMgdGhlIHNhbWUgYWRyZW5hbGluZSBydXNoOyBwb3B1bGFyIG9uZXMgc2VlbSB0byBoYXZlIGEgdHdpc3QgaW4gdGhlIGZvcm11bGEuCgpJIGFtIGN1cmlvdXMgd2hldGhlciBwb3B1bGFyIHBvcCB0cmFja3MgaGF2ZSBkaWZmZXJlbnQgYXR0cmlidXRlcyB0aGF0IG1ha2UgdGhlbSBoaXQgdGhlIHRvcCBjaGFydCBsaXN0cy4gQW5kIHNvLCBJIHdhbnQgdG8gY29tcGFyZSB0aGUgZGF0YSBmb3IgdGhlIGZlYXR1cmVzIG9mIHRyYWNrcyB0byBzZWUgaWYgdGhlIHNlY3JldCBmb3IgdGhlaXIgc3VjY2VzcyBsaWVzIGluIHRlY2huaWNhbCBmZWF0dXJlcy4KCgpgYGB7cn0KZmVhdHVyZV9uYW1lcyA8LSBuYW1lcyhzcG90aWZ5KVsxMjoyM10KCnNwb3RpZnkgJT4lIAogIGZpbHRlcihwbGF5bGlzdF9nZW5yZSA9PSAicG9wIikgJT4lIAogIG11dGF0ZShpc19wb3B1bGFyID0gaWZlbHNlKHRyYWNrX3BvcHVsYXJpdHkgPj0gNzUsIFQsIEYpKSAlPiUgCiAgc2VsZWN0KGMoaXNfcG9wdWxhciwgZmVhdHVyZV9uYW1lcykpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gZmVhdHVyZV9uYW1lcykgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdmFsdWUpKSArCiAgZ2VvbV9kZW5zaXR5KGFlcyhjb2xvciA9IGlzX3BvcHVsYXIpLCBhbHBoYSA9IDAuNSkgKwogIGZhY2V0X3dyYXAofm5hbWUsIG5jb2wgPSAzLCBzY2FsZXMgPSAnZnJlZScpICsKICBsYWJzKHRpdGxlID0gIlBvcHVsYXIgdnMuIFVucG9wdWxhciBTcG90aWZ5IEF1ZGlvIEZlYXR1cmUgRGVuc2l0eSIsCiAgICAgICB4ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgIHkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKG5hbWUgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoInVucG9wdWxhciIsICJwb3B1bGFyIikpCgpgYGAKCkxvb2tpbmcgYXQgdGhlIGRhdGEgZnJvbSB0aGUgcGxvdCBhYm92ZSwgaXQgc2VlbXMgdGhhdCB0aGUgbW9zdCBkaXN0aW5ndWlzaGFibGUgZGlmZmVyZW5jZSB0aGF0IG1ha2VzIHBvcHVsYXIgcG9wIHRyYWNrcyBzdGFuZCBvdXQgaXMgdGhlaXIgZGFuY2VhYmlsaXR5LiBUaGlzIGNhbiBiZSBzZWVuIGZyb20gdGhlIHBlYWsgc2hpZnRlZCB0byB0aGUgcmlnaHQgZm9yIGRhbmNlYWJpbHR5LiBPbmUgdGhpbmcgdGhhdCBzdXJwcmlzZWQgbWUgd2FzIHRvIHNlZSB0aGF0IHBvcHVsYXIgcG9wIHRyYWNrcyB0ZW5kIHRvIGhhdmUgc2xpZ2h0bHkgbG93ZXIgZW5lcmd5IGFuZCBsb3VkbmVzcyB2YWx1ZXMuIEl0IHNlZW1zIHRoYXQgcG9wdWxhciBwb3AgdHJhY2tzIHRlbmQgdG8gZm9jdXMgb24gb3RoZXIgYXNwZWN0cyB0byBtYWtlIHRoZSBzb25nIGZlZWwgbW9yZSBlbmVyZ2l6YWJsZS4gTmV2ZXJ0aGVsZXNzLCBpdCBjYW4gYmUgc2FpZCB0aGF0IHRoZXNlIHRlY2huaWNhbCBmZWF0dXJlcyBhcmVuJ3Qgd2hhdCBkaXN0aW5ndWlzaCB0aGUgdHJhY2tzIHRoYXQgbWFrZSBpdCB0byB0aGUgdG9wIGNoYXJ0cy4KCgojIFdoYXQgbm93PyBXaHkgaXMgb3VyIGFuYWx5c2lzIGltcG9ydGFudD8KCkFzIGl0IGJlY29tZXMgZWFzaWVyIHRvIHByb2R1Y2UgYW5kIHJlbGVhc2UgbXVzaWMgZnJvbSBvbmUncyBvd24gYmVkcm9vbSBhbmQgc3RyZWFtaW5nIHBsYXRmb3JtcyBzdWNoIGFzIEFwcGxlIE11c2ljIGFuZCBTcG90aWZ5IGluY3JlYXNpbmdseSBtYWtpbmcgbXVzaWMgYWNjZXNzaWJsZSB0byBldmVyeW9uZSwgd2UgYmVsaWV2ZSBvdXIgYW5hbHlzaXMgaGFzIGltcG9ydGFudCBpbXBsaWNhdGlvbnMgd2hpY2ggY2FuIGhlbHAgbGlzdGVuZXJzIGZpbmQgbmV3IHNvbmdzIHRoYXQgdGhleSBsaWtlIGFuZCBoZWxwIHBsYXRmb3JtcyBidWlsZCBhbGdvcml0aG1zIHRoYXQgZ2l2ZSBiZXR0ZXIgYW5kIG1vcmUgcmVsZXZhbnQgc29uZyByZWNvbW1lbmRhdGlvbnMgdG8gaXRzIHVzZXJzLiAKCiMjIyBBbiBBY2tub3dsZWRnZW1lbnQ6IENvcnJlbGF0aW9uIGRvZXMgbm8gZXF1YWwgY2F1c2F0aW9uLgoKQXMgd2UgY2xvc2Ugb3VyIGFuYWx5c2lzIG9mIHdoYXQgbWFrZXMgYSBzb25nIHBvcHVsYXIsIGl0IHdvdWxkIGJlIHJlbWlzcyBpZiB3ZSBkaWQgbm90IGFja25vd2xlZGdlIHRoYXQganVzdCBiZWNhdXNlIHdlIGhhdmUgaWRlbnRpZmllZCBjZXJ0YWluIGNoYXJhY3RlcmlzdGljcyB0aGF0IG1ha2UgYSBzb25nIGhhdmUgYSBoaWdoIHBvcHVsYXJpdHkgcmF0aW5nLCBpdCBkb2VzIG5vdCBuZWNlc3NhcmlseSBtZWFuIHRoYXQgKmlmKiBhIGNlcnRhaW4gc29uZyBoYXMgYWxsIHRoZSBwcmVmZXJyZWQgY2hhcmFjdGVyaXN0aWNzIHRoYXQgd2UgbWVudGlvbmVkIGluIG91ciBhbmFseXNlcywgaXQgKndpbGwqIGJlIHBvcHVsYXIsIGFzIHdlIGNhbiBuZXZlciBrbm93IHdoZXRoZXIgb3Igbm90IHNvbWV0aGluZyB3aWxsIHdpdGggMTAwJSBjZXJ0YWlubHkuIApUaGVyZSBpcyBhbHNvIGEgZmFjdG9yIG9mIGh1bWFuIGJlaGF2aW9yIHRoYXQgd2Ugc2ltcGx5IGNhbm5vdCBwcmVkaWN0IHVzaW5nIGRhdGEgc2NpZW5jZS4gV2UgY2FuIHRyeSBvdXIgYmVzdCB0byBmb2xsb3cgdHJlbmRzIGFuZCB0byBsb29rIGF0IGdyYXBocywgYnV0IHRyeWluZyB0byBwcmVkaWN0IHdoZXRoZXIgb3Igbm90IGEgc29uZyB3aWxsbCBiZSB3ZWxsIGxpa2VkIGJ5IGl0cyBhdWRpZW5jZSBpcyBzb21ldGhpbmcgdGhhdCBtdXN0IGJlIHRha2VuIHdpdGggYSBncmFpbiBvZiBzYWx0LiBBdCBpdHMgY29yZSwgdGhlIHB1cnBvc2Ugb2Ygb3VyIGFuYWx5c2lzIHdhcyBzaW1wbHkgdG8gbWFrZSBnZW5lcmFsIG9ic2VydmF0aW9ucyBhYm91dCB0cmVuZHMgdGhhdCBjYXVnaHQgdGhlIGV5ZSAtLSBub3QgdG8gcHJlZGljdCB3aXRoIGNvbXBsZXRlIGNlcnRhaW50eSB0aGUgcG9wdWxhcml0eSBvZiBhIHNvbmcuCgojIyBQb3NzaWJpbGl0aWVzIGZvciBmdXJ0aGVyIGFuYWx5c2lzICYgQSBDb25jbHVzaW9uCklmIHdlIGhhZCBtb3JlIHRpbWUsIHdlIGJlbGlldmUgaXQgd291bGQgYmUgZmFzY2luYXRpbmcgYW5kIHVzZWZ1bCB0byBidWlsZCBhIHNoaW55IGFwcCB3aGVyZSBwZW9wbGUgY291bCBhZGp1c3QgdGhlaXIgcHJlZmVyZW5jZXMgZm9yIGZlYXR1cmVzIHRoZXkgbG9vayBmb3IgaW4gc29uZ3MgdGhlaXIgZmF2b3JpdGUgc29uZ3MgKGVnLiBoaWdoIGRhbmNlYWJpbGl0eSwgbG93IHZhbGVuY2UsIGV0Yy4pIHNvIHRoYXQgdGhlIGFwcCBjb3VsZCByZXR1cm4gcmVjb21tZW5kZWQgc29uZ3Mgd2l0aCBzaW1pbGFyIHZhbHVlcy4gT3IsIHdlIGNvdWxkIGhhdmUgdXNlcnMgaW5wdXQgdGhlaXIgZmF2b3JpdGUgc29uZ3MgdG8gZmluZCByZWNvbW1lbmRhdGlvbnMgYmFzZWQgb24gc2ltaWxhciBjaGFyYWN0ZXJpc3RpYyBhbmQgc29uZyBhdHRyaWJ1dGVzLiBXZSBjb3VsZCBhbHNvIGNyZWF0ZSBwbGF5bGlzdHMsIHNpbWlsYXIgdG8gd2hhdCBTcG90aWZ5IGRvZXMuIEJ5IGRldGVybWluaW5nIHJlY29tbWVuZGVkIHZhbHVlcyBmb3IgZGlmZmVyZW50IG1vb2RzIGFuZCBwdXJwb3NlcyBzdWNoIGFzIHJlbGF4YXRpb24sIG1lZGl0YXRpbmcsIGFuZCBzdHVkeWluZywgaXQgd291bGQgYmUgaW50ZXJzdGluZyB0byBzZWUgaG93IGFjY3VyYXRlIHRoZXNlIHBsYXlsaXN0cyBhcmUuIEFnYWluLCBhcyB3ZSBtZW50aW9uZWQgaW4gdGhlIHByZXZpb3VzIHNlY3Rpb24sIHdlIGNhbm5vdCBwcmVkaWN0IGh1bWFuIGp1ZGdlbWVudCwgc28gd2UgZG8gZXhwZWN0IHNvbWUgbGV2ZWwgb2YgaHVtYW4gZXJyb3IgaW4gZGV0ZXJtaW5pbmcgdGhlICJjb3JyZWN0bmVzcyIgb2YgdGhlIHBsYXlsaXN0cy4gVGhlIHBvc3NpYmlsaXRpZXMgd2l0aCB0aGlzIGRhdGFzZXQgYXJlIGVuZGxlc3MhCgpUaGFua3MgdG8gc3RyZWFtaW5nIHBsYXRmb3JtcyBzdWNoIGFzIFNwb3RpZnkgYW5kIEFwcGxlIE11c2ljLCBzbWFsbCBjcmVhdG9ycyBhcmUgYWxzbyBnaXZlbiBhIHBsYXRmb3JtIGZvciBjcmVhdGl2ZSByZWxlYXNlLiBPdXIgYW5hbHlzZXMgb2YgcG9wLCByYXAsIGFuZCBSJkIsIGNhbiBhbHNvIGhlbHAgc21hbGwgYXJ0aXN0cyBncm93IHRoZWlyIG93biBwbGF0Zm9ybXMgdG8gY2F0ZXIgdG8gdGhlIGludGVyZXN0cyBvZiBzcGVjaWZpYyBhdWRpZW5jZXMuIEluIGEgdGltZSBzdWNoIGFzIG5vdyB3aGVuIHRoZSBjb25zdW1wdGlvbiBvZiBhcnQgKHdoZXRoZXIgaXQgYmUgaW4gdGhlIGZvcm0gb2YgbW92aWVzLCBtdXNpYywgb3IgdGVsZXZpc2lvbiksIGlzIGVzc2VudGlhbCB0byBvbmUncyBtZW50YWwgd2VsbGJlaW5nLCBvdXIgYW5hbHlzaXMgY2FuIGhlbHAgYm9vc3QgdGhlc2UgZWZmb3J0cy4gQnkgYXNraW5nIHRoZSBxdWVzdGlvbiwgIldoYXQgbWFrZXMgYSBzb25nIGluIGEgZ2l2ZW4gZ2VucmUgcG9wdWxhcj8iIFdlIGhhdmUgdGFrZW4gYSBjbG9zZSBsb29rIGF0IHRoZSBzcGVjaWZpYyBjaGFyYWN0ZXJpc3RpY3Mgb2Ygc29uZ3Mgd2l0aCBhIHBvcHVsYXJpdHkgcmF0aW5nIG9mIDc1IG9yIGhpZ2hlci4KCgoKCgo=